﻿using Acme.BookStore.Purchase.Customergoods;
using Acme.BookStore.PurchaseDto.CustomergoodsDto;
using Acme.BookStore.PurchaseDto.OtherwarehousingDto;
using Microsoft.DotNet.PlatformAbstractions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Caching.Distributed;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Caching;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Identity;
using System.Linq.Dynamic.Core;
using Microsoft.EntityFrameworkCore;

namespace Acme.BookStore.Purchase.Otherwarehousing
{
    public class OtherwarehousingServices: CrudAppService
        <OtherwarehousingModel, OtherwarehousingDto, Guid, PagedResultRequestDto, CreateUpdateOtherwarehousingDto>, IOtherwarehousingServices
    {
        private readonly IRepository<IdentityUser, Guid> _userRepository;
        private readonly IDistributedCache<PagedResultDto<OtherwarehousingDto>, string> _otherwarehousingDtoCache;
        private readonly ILogger<OtherwarehousingServices> _logger;

        public OtherwarehousingServices(
            IRepository<OtherwarehousingModel, Guid> repository,
            IRepository<IdentityUser, Guid> userRepository, 
            IDistributedCache<PagedResultDto<OtherwarehousingDto>, string>otherwarehousingDtoCache,
            ILogger<OtherwarehousingServices> logger)
            :base(repository)
        {
            _userRepository = userRepository;
            _otherwarehousingDtoCache = otherwarehousingDtoCache;
            _logger = logger;
        }

        public async Task<ListResultDto<IOtherwarehousingServices.OrderTypeModelDto>> GetOrderTypeModelAsync()
        {
            var list = Enum.GetValues(typeof(OrderTypeModel))
               .Cast<OrderTypeModel>()
               .Select(x => new IOtherwarehousingServices.OrderTypeModelDto
               {
                   Id = (int)x,
                   Name = x.ToString()
               }).ToList();

            return new ListResultDto<IOtherwarehousingServices.OrderTypeModelDto>(list);
        }

        public async Task<ListResultDto<IOtherwarehousingServices.PlatformDto>> GetPlatformDtoModelAsync()
        {
            var list = Enum.GetValues(typeof(PlatformEnum))
              .Cast<PlatformEnum>()
              .Select(x => new IOtherwarehousingServices.PlatformDto
              {
                  Id = (int)x,
                  Name = x.ToString()
              }).ToList();

            return new ListResultDto<IOtherwarehousingServices.PlatformDto>(list);
        }

        public async Task<ListResultDto<IOtherwarehousingServices.ReservedWarehouseAreaModelDto>> GetReservedWarehouseAreaModelAsync()
        {
            var list = Enum.GetValues(typeof(ReservedWarehouseAreaModel))
                .Cast<ReservedWarehouseAreaModel>()
                .Select(x => new IOtherwarehousingServices.ReservedWarehouseAreaModelDto
                {
                    Id = (int)x,
                    Name = x.ToString()
                }).ToList();

            return new ListResultDto<IOtherwarehousingServices.ReservedWarehouseAreaModelDto>(list);
        }

        public async Task<ListResultDto<IOtherwarehousingServices.WarehouseModelDto>> GetWarehouseModelAsync()
        {
            var list = Enum.GetValues(typeof(WarehouseModel))
                .Cast<WarehouseModel>()
                .Select(x => new IOtherwarehousingServices.WarehouseModelDto
                {
                    Id = (int)x,
                    Name = x.ToString()
                }).ToList();

            return new ListResultDto<IOtherwarehousingServices.WarehouseModelDto>(list);
        }

        /// <summary>
        /// 根据条件查询其他入库单
        /// </summary>
        public async Task<PagedResultDto<OtherwarehousingDto>> GetListByConditionsAsync(OtherwarehousingQueryDto input)
        {
            try
            {
                // 构建缓存键
                var cacheKey = $"OtherwarehousingQuery:{input.PurchaseOrderNo}:{input.ExpectedArrivalDateFrom}:{input.ExpectedArrivalDateTo}:{input.CustomerOrderNo}:{input.CarNo}:{input.DriverName}:{input.DriverPhone}:{input.Status}:{input.Platform}";

                // 尝试从缓存获取
                var cachedResult = await _otherwarehousingDtoCache.GetAsync(cacheKey);
                if (cachedResult != null)
                {
                    _logger.LogInformation($"Cache hit for key: {cacheKey}");
                    return cachedResult;
                }
                _logger.LogInformation($"Cache miss for key: {cacheKey}");

                // 获取查询对象
                var query = await Repository.GetQueryableAsync();

                // 应用查询条件
                query = query.WhereIf(
                    !string.IsNullOrWhiteSpace(input.PurchaseOrderNo),
                    x => x.OrderNo.Contains(input.PurchaseOrderNo)
                ).WhereIf(
                    !string.IsNullOrWhiteSpace(input.OwnerCode),
                    x => x.OwnerCode.Contains(input.OwnerCode)
                ).WhereIf(
                    input.OrderType.HasValue,
                    x => x.OrderType == input.OrderType
                )
                .WhereIf(
                    input.ExpectedArrivalDateFrom.HasValue,
                    x => x.EstimatedArrivalTime >= input.ExpectedArrivalDateFrom.Value
                )
                .WhereIf(
                    input.ExpectedArrivalDateTo.HasValue,
                    x => x.EstimatedArrivalTime <= input.ExpectedArrivalDateTo.Value
                )
                .WhereIf(
                    !string.IsNullOrWhiteSpace(input.CustomerOrderNo),
                    x => x.CustomerOrderNo.Contains(input.CustomerOrderNo)
                )
                .WhereIf(
                    !string.IsNullOrWhiteSpace(input.CarNo),
                    x => x.CarNo.Contains(input.CarNo)
                )
                .WhereIf(
                    !string.IsNullOrWhiteSpace(input.DriverName),
                    x => x.DriverName.Contains(input.DriverName)
                )
                .WhereIf(
                    !string.IsNullOrWhiteSpace(input.DriverPhone),
                    x => x.DriverPhone.Contains(input.DriverPhone)
                )
                .WhereIf(
                    !string.IsNullOrWhiteSpace(input.Status),
                    x => x.Status == input.Status
                )
                .WhereIf(
                    input.Platform.HasValue,
                    x => x.Platform == input.Platform
                );

                // 获取总数
                var totalCount = await AsyncExecuter.CountAsync(query);

                // 排序和分页
                var items = await AsyncExecuter.ToListAsync(
                    query.OrderBy(input.Sorting ?? nameof(OtherwarehousingModel.Id))
                        .Skip(input.SkipCount)
                        .Take(input.MaxResultCount)
                );

                // 转换为DTO
                var dtos = ObjectMapper.Map<List<OtherwarehousingModel>, List<OtherwarehousingDto>>(items);
                var result = new PagedResultDto<OtherwarehousingDto>(totalCount, dtos);

                // 保存到缓存
                await _otherwarehousingDtoCache.SetAsync(
                    cacheKey,
                    result,
                    new DistributedCacheEntryOptions
                    {
                        AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10)
                    }
                );

                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error occurred while searching other warehousing records");
                throw;
            }
        }
    }
}
